﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace Utils.XML
{
    public class XML
    {
        public static XmlNodeList GetXmlNodeList(string file, string xpath)
        {
            XmlDocument xmldoc = GetXML(file);

            return GetXmlNodeList(xmldoc, xpath);
        }

        public static XmlNodeList GetXmlNodeList(XmlDocument xmldoc, string xpath)
        {
            XmlNamespaceManager xmlns = new XmlNamespaceManager(xmldoc.NameTable);
            XmlNodeList xmlnodelist = xmldoc.SelectNodes(xpath, xmlns);

            return xmlnodelist;
        }

        public static XmlDocument GetXML(string filepath)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(filepath);
            return doc;
        }

        public static bool SaveFile(string filepath, object o)
        {
            bool result = true;
            try
            {
                StringWriterWithEncoding writer = new StringWriterWithEncoding(Encoding.UTF8);
                XmlSerializer serializer = new XmlSerializer(o.GetType());
                serializer.Serialize(writer, o);
                string xml = writer.ToString();
                XmlTextWriter textWriter = new XmlTextWriter(filepath, null);
                textWriter.WriteRaw(xml);
                textWriter.Close();
            }
            catch 
            {
                result = false;
            }

            return result;
        }

        public static object LoadFile(string filepath, Type type)
        {
            XmlDocument xml = GetXML(filepath);
            StringReader reader = new StringReader(xml.InnerXml);
            XmlSerializer serializer = new XmlSerializer(type);
            return serializer.Deserialize(reader);

        }

        /// <summary>
        /// Serializes an object into an Xml Document
        /// </summary>
        /// <param name="o">The object to serialize</param>
        /// <returns>An Xml Document consisting of said object's data</re
        //public static XmlDocument Serialize(object o)
        //{
        //    XmlSerializer s = new XmlSerializer(o.GetType());

        //    //MemoryStream ms = new MemoryStream();
        //    Stream xmlFile = new FileStream(@"c:\list.xml", FileMode.Append, FileAccess.Write);
        //    StreamWriter writer = new StreamWriter(xmlFile, new UTF8Encoding());
        //    /*writer.Formatting = Formatting.Indented;
        //    writer.IndentCha = ' ';
        //    writer.Indentation = 5;*/
        //    Exception caught = null;

        //    try
        //    {
        //        s.Serialize(writer, o);
        //        XmlDocument xml = new XmlDocument();
        //        string xmlString = xmlFile.ToString();
        //        xml.LoadXml(xmlString);
        //        return xml;
        //    }
        //    catch (Exception e)
        //    {
        //        caught = e;
        //    }
        //    finally
        //    {
        //        writer.Close();
        //        xmlFile.Close();

        //        if (caught != null)
        //            throw caught;
        //    }
        //    return null;
        //}

        /// <summary>
        /// Deserializes an xml document back into an object
        /// </summary>
        /// <param name="xml">The xml data to deserialize</param>
        /// <param name="type">The type of the object being deserialized</param>
        /// <returns>A deserialized object</returns>
        //public static object Deserialize(XmlDocument xml, Type type)
        //{
        //    XmlSerializer s = new XmlSerializer(type);
        //    string xmlString = xml.OuterXml.ToString();
        //    byte[] buffer = ASCIIEncoding.UTF8.GetBytes(xmlString);
        //    MemoryStream ms = new MemoryStream(buffer);
        //    XmlReader reader = new XmlTextReader(ms);
        //    Exception caught = null;

        //    try
        //    {
        //        object o = s.Deserialize(reader);
        //        return o;
        //    }

        //    catch (Exception e)
        //    {
        //        caught = e;
        //    }
        //    finally
        //    {
        //        reader.Close();

        //        if (caught != null)
        //            throw caught;
        //    }
        //    return null;
        //}
    }

    public class StringWriterWithEncoding : StringWriter
    {
        Encoding encoding;

        public StringWriterWithEncoding(Encoding encoding)
        {
            this.encoding = encoding;
        }

        public override Encoding Encoding
        {
            get { return encoding; }
        }
    }
}
